//+------------------------------------------------------------------+
//|                                                   ArrayULong.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include "Array.h"  // 引入基础数组类，CArrayULong 继承自 CArray
//+------------------------------------------------------------------+
//| CArrayULong 类                                                   |
//| 功能：管理 ulong 类型（无符号64位整数）的动态数组类              |
//| 核心特性：超大取值范围（0~18446744073709551615）、8字节内存占用  |
//| 继承关系：派生自 CArray 基础类，支持无符号64位整数的动态管理操作 |
//+------------------------------------------------------------------+
class CArrayULong : public CArray
  {
protected:
   ulong              m_data[];           // 存储无符号64位整数的核心数组容器（每个元素占8字节）

public:
   /**
    * @brief 构造函数：初始化 CArrayULong 类实例
    * @details 初始化数组容量（m_data_max）、已存储元素数量（m_data_total）等成员变量，
    *          为无符号64位整数存储做准备，初始容量由 ArraySize(m_data) 确定
    */
                     CArrayULong(void);

   /**
    * @brief 析构函数：销毁 CArrayULong 类实例
    * @details 调用 Shutdown 方法释放数组占用的内存（8字节元素批量释放，避免内存泄漏）
    */
                    ~CArrayULong(void);

   //--- 对象类型识别方法
   /**
    * @brief 获取当前数组对象的类型标识
    * @return int - 类型标识，固定返回 TYPE_ULONG（表示无符号64位整数类型数组）
    */
   virtual int       Type(void) const { return(TYPE_ULONG); }

   //--- 文件操作相关方法（按8字节无符号整数格式读写）
   /**
    * @brief 将数组中的无符号64位整数数据写入指定文件
    * @details 先写入数组长度（INT_VALUE格式），再按8字节无符号整数格式写入每个元素
    * @param file_handle [in] 已打开的文件句柄（需包含写入权限，支持文本/二进制模式）
    * @return bool - 操作结果：true 表示所有元素均写入成功，false 表示任一元素写入失败
    */
   virtual bool      Save(const int file_handle);

   /**
    * @brief 从指定文件读取无符号64位整数数据到数组
    * @details 先读取数组长度，再按8字节无符号整数格式读取每个元素，自动适配0~18446744073709551615范围
    * @param file_handle [in] 已打开的文件句柄（需包含读取权限，支持文本/二进制模式）
    * @return bool - 操作结果：true 表示所有元素均读取成功，false 表示读取失败（如文件格式错误）
    */
   virtual bool      Load(const int file_handle);

   //--- 动态内存管理方法
   /**
    * @brief 为数组预留指定大小的空闲内存空间
    * @details 检查当前剩余空闲空间，不足时按预设步长扩容（8字节元素扩容需注意内存占用）
    * @param size [in] 需要预留的空闲元素（无符号64位整数）数量
    * @return bool - 操作结果：true 表示预留成功，false 表示 size≤0 或内存分配失败
    */
   bool              Reserve(const int size);

   /**
    * @brief 调整数组总容量（超出容量的元素会被截断删除）
    * @param size [in] 调整后的数组总容量（总内存占用=size×8字节）
    * @return bool - 操作结果：true 表示容量调整成功，false 表示 size<0 或内存分配失败
    */
   bool              Resize(const int size);

   /**
    * @brief 彻底清空数组并释放所有占用的内存
    * @details 重置数组数据、总容量、已存储元素数量等成员变量，将8字节元素占用的内存归还给系统
    * @return bool - 操作结果：true 表示清理成功，false 表示数组内存释放失败
    */
   bool              Shutdown(void);

   //--- 数组填充相关方法（需注意无符号64位特性和超大取值范围）
   /**
    * @brief 向数组末尾添加一个无符号64位整数元素
    * @param element [in] 要添加的 ulong 类型元素（取值范围：0~18446744073709551615，
    *                     超出范围会自动截断为64位无符号值）
    * @return bool - 操作结果：true 表示添加成功，false 表示内存不足
    */
   bool              Add(const ulong element);

   /**
    * @brief 将外部 ulong 数组的所有元素添加到当前数组末尾
    * @param src [in] 外部 ulong 类型数组（需传入数组引用，元素自动适配无符号64位范围）
    * @return bool - 操作结果：true 表示所有元素添加成功，false 表示内存不足
    */
   bool              AddArray(const ulong &src[]);

   /**
    * @brief 将另一个 CArrayULong 实例的所有元素添加到当前数组末尾
    * @param src [in] 指向另一个 CArrayULong 实例的指针（需先通过 CheckPointer 验证有效性）
    * @return bool - 操作结果：true 表示添加成功，false 表示指针无效或内存不足
    */
   bool              AddArray(const CArrayULong *src);

   /**
    * @brief 在数组指定索引位置插入一个无符号64位整数元素
    * @details 插入位置及后续元素自动后移（8字节元素移动需注意性能开销），数组长度加1
    * @param element [in] 要插入的 ulong 类型元素（需在0~18446744073709551615范围内）
    * @param pos [in] 插入位置的索引（从0开始，需满足 0≤pos≤当前数组长度）
    * @return bool - 操作结果：true 表示插入成功，false 表示位置无效或内存不足
    */
   bool              Insert(const ulong element,const int pos);

   /**
    * @brief 将外部 ulong 数组的所有元素插入到当前数组指定位置
    * @param src [in] 外部 ulong 类型数组（需传入数组引用）
    * @param pos [in] 插入位置的索引（从0开始，需满足 0≤pos≤当前数组长度）
    * @return bool - 操作结果：true 表示插入成功，false 表示位置无效或内存不足
    */
   bool              InsertArray(const ulong &src[],const int pos);

   /**
    * @brief 将另一个 CArrayULong 实例的所有元素插入到当前数组指定位置
    * @param src [in] 指向另一个 CArrayULong 实例的指针（需验证指针有效性）
    * @param pos [in] 插入位置的索引（从0开始，需满足 0≤pos≤当前数组长度）
    * @return bool - 操作结果：true 表示插入成功，false 表示指针无效、位置无效或内存不足
    */
   bool              InsertArray(const CArrayULong *src,const int pos);

   /**
    * @brief 用外部 ulong 数组的内容覆盖当前数组（赋值操作）
    * @details 先清空当前数组所有元素，再将外部数组的无符号64位整数完整复制（8字节复制效率需注意）
    * @param src [in] 外部 ulong 类型数组（需传入数组引用）
    * @return bool - 操作结果：true 表示赋值成功，false 表示内存不足
    */
   bool              AssignArray(const ulong &src[]);

   /**
    * @brief 用另一个 CArrayULong 实例的内容覆盖当前数组（赋值操作）
    * @details 先清空当前数组所有元素，再复制源实例的元素和排序状态（保持无符号64位特性一致性）
    * @param src [in] 指向另一个 CArrayULong 实例的指针（需验证指针有效性）
    * @return bool - 操作结果：true 表示赋值成功，false 表示指针无效或内存不足
    */
   bool              AssignArray(const CArrayULong *src);

   //--- 数组元素访问方法（无效索引返回LONG_MAX，需注意与有效元素区分）
   /**
    * @brief 获取数组指定索引位置的无符号64位整数元素
    * @param index [in] 要访问的元素索引（从0开始，需满足 0≤index<当前数组长度）
    * @return ulong - 对应索引的元素（0~18446744073709551615）；
    *                 若索引无效，返回 LONG_MAX（9223372036854775807，需注意其为有效 ulong 值）
    */
   ulong             At(const int index) const;

   /**
    * @brief 重载 [] 运算符，通过索引直接访问数组元素（等价于 At 方法）
    * @param index [in] 要访问的元素索引（从0开始，需满足 0≤index<当前数组长度）
    * @return ulong - 对应索引的元素（0~18446744073709551615）；
    *                 若索引无效，返回 LONG_MAX（9223372036854775807）
    */
   ulong operator[](const int index) const { return(At(index)); }

   //--- 最小值/最大值查找方法（适配无符号64位范围）
   /**
    * @brief 在数组指定范围内查找最小无符号64位整数的索引
    * @param start [in] 查找范围的起始索引（从0开始）
    * @param count [in] 查找的元素个数（需满足 start + count ≤ 当前数组长度）
    * @return int - 最小元素所在的索引；若范围无效，返回 -1
    */
   int               Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); }

   /**
    * @brief 在数组指定范围内查找最大无符号64位整数的索引
    * @param start [in] 查找范围的起始索引（从0开始）
    * @param count [in] 查找的元素个数（需满足 start + count ≤ 当前数组长度）
    * @return int - 最大元素所在的索引；若范围无效，返回 -1
    */
   int               Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); }

   //--- 数组元素修改方法
   /**
    * @brief 更新数组指定索引位置的无符号64位整数元素
    * @param index [in] 要更新的元素索引（需满足 0≤index<当前数组长度）
    * @param element [in] 新的 ulong 类型元素（取值范围：0~18446744073709551615，超出范围会自动截断）
    * @return bool - 操作结果：true 表示更新成功，false 表示索引无效
    */
   bool              Update(const int index,const ulong element);

   /**
    * @brief 将数组指定索引的元素按指定偏移量移动位置
    * @details 8字节元素移动可能产生性能开销，建议批量操作时优化
    * @param index [in] 要移动的元素原始索引（需在有效范围内）
    * @param shift [in] 偏移量（正数表示向后移动，负数表示向前移动，需确保移动后位置有效）
    * @return bool - 操作结果：true 表示移动成功，false 表示位置越界或偏移量为0
    */
   bool              Shift(const int index,const int shift);

   //--- 数组元素删除方法
   /**
    * @brief 删除数组指定索引位置的元素
    * @details 删除后，后续元素自动前移（8字节元素移动需注意性能），数组长度减1
    * @param index [in] 要删除的元素索引（需满足 0≤index<当前数组长度）
    * @return bool - 操作结果：true 表示删除成功，false 表示索引无效
    */
   bool              Delete(const int index);

   /**
    * @brief 删除数组中指定范围的元素（闭区间 [from, to]）
    * @details 删除后，后续元素自动前移，数组长度减少（to - from + 1）
    * @param from [in] 删除范围的起始索引（需≥0）
    * @param to [in] 删除范围的结束索引（需≥from 且 < 当前数组长度）
    * @return bool - 操作结果：true 表示删除成功，false 表示范围无效
    */
   bool              DeleteRange(int from,int to);

   //--- 数组比较方法（按无符号64位值严格匹配）
   /**
    * @brief 比较当前数组与外部 ulong 数组是否完全相等
    * @details 需满足：1. 元素个数相同；2. 对应位置的 ulong 值严格相等（无符号64位值无精度误差）
    * @param array [in] 要比较的外部 ulong 类型数组（需传入数组引用）
    * @return bool - 比较结果：true 表示完全相等，false 表示不相等（长度/元素值不同）
    */
   bool              CompareArray(const ulong &array[]) const;

   /**
    * @brief 比较当前数组与另一个 CArrayULong 实例是否完全相等
    * @details 需满足：1. 元素个数相同；2. 对应位置的 ulong 值严格相等（无符号特性一致）
    * @param array [in] 指向要比较的 CArrayULong 实例的指针（需验证指针有效性）
    * @return bool - 比较结果：true 表示完全相等，false 表示不相等（指针无效/长度/元素值不同）
    */
   bool              CompareArray(const CArrayULong *array) const;

   //--- 有序数组操作方法（按无符号64位值大小排序）
   /**
    * @brief 向有序数组中插入元素（保持数组升序/降序特性，按0~18446744073709551615数值大小排序）
    * @param element [in] 要插入的 ulong 类型元素（0~18446744073709551615）
    * @return bool - 操作结果：true 表示插入成功且数组保持有序，false 表示数组未排序或内存不足
    */
   bool              InsertSort(const ulong element);

   /**
    * @brief 在有序数组中查找指定无符号64位元素的索引
    * @param element [in] 要查找的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回对应索引，未找到/数组未排序返回 -1
    */
   int               Search(const ulong element) const;

   /**
    * @brief 在有序数组中查找第一个“大于”指定无符号64位元素的索引（按数值大小）
    * @param element [in] 参考的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回对应索引，未找到（如所有元素≤目标）/数组未排序返回 -1
    */
   int               SearchGreat(const ulong element) const;

   /**
    * @brief 在有序数组中查找第一个“小于”指定无符号64位元素的索引（按数值大小）
    * @param element [in] 参考的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回对应索引，未找到（如所有元素≥目标）/数组未排序返回 -1
    */
   int               SearchLess(const ulong element) const;

   /**
    * @brief 在有序数组中查找第一个“大于或等于”指定无符号64位元素的索引
    * @param element [in] 参考的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回对应索引，未找到/数组未排序返回 -1
    */
   int               SearchGreatOrEqual(const ulong element) const;

   /**
    * @brief 在有序数组中查找第一个“小于或等于”指定无符号64位元素的索引
    * @param element [in] 参考的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回对应索引，未找到/数组未排序返回 -1
    */
   int               SearchLessOrEqual(const ulong element) const;

   /**
    * @brief 在有序数组中查找指定无符号64位元素第一次出现的索引
    * @param element [in] 要查找的 ulong 类型元素（数组中可能存在多个相同值）
    * @return int - 查找结果：找到时返回第一次出现的索引，未找到/数组未排序返回 -1
    */
   int               SearchFirst(const ulong element) const;

   /**
    * @brief 在有序数组中查找指定无符号64位元素最后一次出现的索引
    * @param element [in] 要查找的 ulong 类型元素（数组中可能存在多个相同值）
    * @return int - 查找结果：找到时返回最后一次出现的索引，未找到/数组未排序返回 -1
    */
   int               SearchLast(const ulong element) const;

   /**
    * @brief 对数组进行线性查找（遍历数组，适用于无序数组，按数值严格匹配）
    * @details 遍历8字节元素数组可能产生性能开销，大数据量建议先排序再用二分查找
    * @param element [in] 要查找的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找结果：找到时返回第一个匹配元素的索引，未找到返回 -1
    */
   int               SearchLinear(const ulong element) const;

protected:
   /**
    * @brief 快速排序算法：对数组指定范围元素按无符号64位数值排序（内部使用，不对外暴露）
    * @param beg [in] 排序范围的起始索引（需≥0）
    * @param end [in] 排序范围的结束索引（需≥beg 且 < 当前数组容量）
    * @param mode [in] 排序模式（默认0，通常表示升序，具体逻辑继承自父类 CArray）
    */
   virtual void      QuickSort(int beg,int end,const int mode=0);

   /**
    * @brief 快速查找算法：在有序数组中定位无符号64位元素位置（内部使用，为 Search 系列提供支持）
    * @details 基于二分法实现，按0~18446744073709551615数值大小比较，返回精确匹配或近似位置的索引
    * @param element [in] 要查找的 ulong 类型元素（0~18446744073709551615）
    * @return int - 查找的位置索引（若找到则为匹配元素索引，未找到则为最后比较的中间位置）
    */
   int               QuickSearch(const ulong element) const;

   /**
    * @brief 数组内部内存移动：将指定范围的无符号64位元素从源位置复制到目标位置（内部使用）
    * @details 用于插入、删除等操作时的元素位置调整，8字节元素复制需注意性能开销
    * @param dest [in] 目标位置的起始索引（需≥0）
    * @param src [in] 源位置的起始索引（需≥0）
    * @param count [in] 要移动的元素个数（需满足 src + count ≤ 当前数组长度）
    * @return int - 操作结果：成功返回目标位置起始索引，失败返回 -1
    */
   int               MemMove(const int dest,const int src,int count);
  };
//+------------------------------------------------------------------+
